#
# "@(#) $Id: cdinfo.py,v 1.1.1.1 2006-07-27 03:16:08 gioshe Exp $"
#
# This work is released under the GNU GPL, version 2 or later.
#
import os, fcntl, array, warnings, re
import CDDB

warnings.filterwarnings('ignore',category=FutureWarning)

#def fixslashes(s):
#	return re.sub(r'/',r'-',s)
	
def disc_id(driver = '/dev/cdrom'):
	fd = os.open(driver,os.O_RDONLY,os.O_NONBLOCK)
	numTracks = getNumTracks(fd)
	print "NUMTraCK",numTracks
	if numTracks!=None:
		trackStarts = getTrackStarts(fd,numTracks)
		checksum = 0
		for track in trackStarts:
			checksum = checksum+sum(track[0]*60+track[1])
		leadOut = getLeadOut(fd)
		os.close(fd)
		totalTime = frames(leadOut)/75-frames(trackStarts[0])/75
		checksum = ((checksum % 0xff)<<24) | totalTime << 8 | numTracks
		result = [checksum,numTracks]
		for track in trackStarts:
			result.append(frames(track))
		result.append(frames(leadOut)/75)
		return result
	return None

def frames(msf):
	return (msf[0]*60+msf[1])*75+msf[2]

def sum(n):
	result = 0
	while n>0:
		result = result+ (n % 10)
		n = n / 10
	return result

def getNumTracks(fd):
	try:
		# the old way of doing ioctl with results
		s = fcntl.ioctl(fd,0x5305,'  ')
		return ord(s[1])
		'''
		# the new way of doing ioctl with results
		a = array.array('b',[0,0])
		s = fcntl.ioctl(fd,0x5305,a,1)
		if s==0:
			return a[1]
		'''
	except: return None

def getTrackStarts(fd,numTracks):
	trackStarts = []
	for i in range(1,numTracks+1):
		trackStarts.append(getTrackStart(fd,i))
	return trackStarts

def getLeadOut(fd):
	return getTrackStart(fd,0xAA)

def getTrackStart(fd,track):
	#a = chr(track)+' '+chr(2)+'     '
	#a = fcntl.ioctl(fd,0x5306,a)
	#return (ord(a[4]),ord(a[5]),ord(a[6]))
	a = array.array('B',[track,0,2,0,0,0,0,0])
	s = fcntl.ioctl(fd,0x5306,a,1)
	return (a[4],a[5],a[6])

def getCDDBInfo(id):
	try:
		print "start query"
		(query_status,query_info) = CDDB.query(id,client_name='Lsongs',client_version='1.0')
		print "end query"
		#print query_status,query_info
		if query_status in [200,210,211]:
			if query_status == 200:
				query_info = [query_info]
			result = []
			for query in query_info[-1:]: # XXX DSM just fetch the last one
				(read_status,read_info) = CDDB.read(query['category'],query['disc_id'])
				if read_status==210:
					result.append({'query':query,'data':read_info})
			return result
		else:
			return None
	except: return None

def getCookedCDDBInfo(id):
	return cookCDDBInfo(id,getCDDBInfo(id))

def cookCDDBInfo(id,info):
	if info!=None:
		trackLists = []
		artistAlbum = re.compile(r'^(.+?) / (.+?)$')
		for item in info:
			tracks = []
			trackNames = {}
			query = item['query']
			data = item['data']
			dtitle = data['DTITLE']
			mo = artistAlbum.search(dtitle)
			artist = "Unknown Artist"
			album = "Unknown Album"
			genre = None
			year = None
			if mo:
				artist = unicode(mo.group(1),'latin-1')
				album = unicode(mo.group(2),'latin-1')
			try: genre = data['DGENRE']
			except: pass
			try: year = int(data['DYEAR'])
			except: pass
			numTracks = id[1]
			#print "number of tracks",numTracks
			for i in range(0,numTracks):
				track = {}
				track['Artist'] = artist
				track['Album'] = album
				key = "TTITLE%d" % i
				track['Title'] = unicode(data[key],'latin-1')
				mo = artistAlbum.search(track['Title'])
				if mo:
					track['Artist'] = mo.group(1)
					track['Title'] = mo.group(2)
					track['Compilation'] = True
				start = id[2+i]*1000/75
				if i==numTracks-1: end = id[3+i]*1000
				else: end = id[3+i]*1000/75
				track['Total Time'] = end-start
				track['Track Number'] = i+1
				track['Track Count'] = numTracks
				if genre: track['Genre'] = genre
				if year: track['Year'] = year
				if trackNames.has_key(track['Title']): # handle possible duplicate track names
					index = 1
					while True:
						newName = track['Title']+("(%d)" % index)
						if not trackNames.has_key(newName):
							break
						index = index+1
					track['Title'] = newName
				trackNames[track['Title']] = 1
				tracks.append(track)
			trackLists.append(tracks)
		return {'Disc ID': id,'Playlists':trackLists}
	else: return None

if __name__=='__main__':
	id = disc_id()
	print id
	print getCookedCDDBInfo(id)
	
